﻿using Microsoft.Extensions.Logging;
using Puppy.Scheduler.Common;
using System;
using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace Puppy.Scheduler.Processors
{
    /// <summary>
    /// HTTP 处理器
    /// </summary>
    public class HttpProcessor : ProcessorBase
    {
        protected IPuppyHttpClientFactory PuppyHttpClientFactory { get; }

        public HttpProcessor(IPuppyHttpClientFactory puppyHttpClientFactory)
        {
            PuppyHttpClientFactory = puppyHttpClientFactory;
        }

        protected override async Task<ProcessResult> ExecuteAsync(TaskContext taskContext, CancellationToken cancellationToken = default)
        {
            var httpParams = JsonSerializer.Deserialize<HttpParams>(taskContext.ParseParams());

            if (httpParams.Url.IsNullOrEmpty())
                return new ProcessResult(false, "URL cant't be empty!");

            if (!httpParams.Url.StartsWith("http"))
                httpParams.Url = "http://" + httpParams.Url;

            Logger.LogInformation("request url: {Url}", httpParams.Url);

            // set default method
            if (httpParams.Method == null)
            {
                httpParams.Method = HttpMethod.Get;
                Logger.LogInformation("using default request method: GET");
            }
            else
            {
                Logger.LogInformation("request method: {Method}", httpParams.Method);
            }

            // default timeout
            Logger.LogInformation("request timeout: {Timeout} seconds", httpParams.Timeout.TotalSeconds);

            // set default mediaType
            if (httpParams.MediaType.IsNullOrEmpty() && httpParams.Method != HttpMethod.Get)
            {
                httpParams.MediaType = MediaTypeNames.Application.Json;
                Logger.LogWarning($"try to use '{MediaTypeNames.Application.Json}' as media type");
            }

            // build http
            var httpClient = PuppyHttpClientFactory.Create(taskContext.TaskName);
            httpClient.Timeout = httpParams.Timeout;

            if (httpParams.Headers != null)
            {
                foreach (var item in httpParams.Headers)
                {
                    httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                    Logger.LogInformation("add header {Key}:{Value}", item.Key, item.Value);
                }
            }

            HttpRequestMessage httpRequest = new(httpParams.Method, httpParams.Url);
            if (!httpParams.Body.IsNullOrWhiteSpace())
            {
                httpRequest.Content = new StringContent(httpParams.Body, Encoding.Default, httpParams.MediaType);
            }
            var httpResponse = await httpClient.SendAsync(httpRequest, cancellationToken);

            if (httpResponse.IsSuccessStatusCode)
            {
                var msg = await httpResponse.Content.ReadAsStringAsync();

                return new ProcessResult(true, msg);
            }
            else
            {
                return new ProcessResult(false, httpResponse.ReasonPhrase);
            }
        }
    }
}
